package com.cngphone.AnFetion.Fetion.SIPC;

import java.util.ArrayList;
import java.util.HashSet;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.cngphone.AnFetion.FetionFriend;
import com.cngphone.AnFetion.FetionSIPC;
import com.cngphone.AnFetion.FetionService;
import com.cngphone.AnFetion.FetionUri;
import com.cngphone.AnFetion.IFriendInfoChanged;
import com.cngphone.AnFetion.Fetion.TcpSendAndReceive;
import com.cngphone.AnFetion.Fetion.TcpSendAndReceive.IPackageReceivedHandler;
import com.cngphone.AnFetion.tools.StrUtil;

public class GetContactsInfo extends SIPCBase implements
		IPackageReceivedHandler {
	private FetionService ctx;
	private FetionUri fetionid;
	private HashSet<IFriendInfoChanged> _friendInfoChangedListener = new HashSet<IFriendInfoChanged>();

	public GetContactsInfo(FetionService ctx, FetionUri fetionid,
			TcpSendAndReceive connection, SerialManager serialManager) {
		super(serialManager, connection);
		this.ctx = ctx;
		this.fetionid = fetionid;
	}

	private boolean getContactsInfo(ArrayList<FetionFriend> updateBuddies) {

		ArrayList<FetionSIPC.HeaderPair> headers = new ArrayList<FetionSIPC.HeaderPair>();
		headers.add(new FetionSIPC.HeaderPair("F", this.fetionid.getId()));
		headers.add(new FetionSIPC.HeaderPair("I", serialManager.getISerial()
				+ " "));
		headers.add(new FetionSIPC.HeaderPair("Q", this.serialManager
				.getSSerial()
				+ " S"));
		headers.add(new FetionSIPC.HeaderPair("N", "GetContactsInfo"));
		StringBuilder body = new StringBuilder(
				"<args><contacts attributes=\"provisioning;impresa;mobile-no;")
				.append("nickname;name;portrait-crc;ivr-enabled\" extended-attributes=\"score-level\">");
		for (int i = 0; i < updateBuddies.size(); i++) {
			body.append("<contact uri=\"").append(updateBuddies.get(i).Uri)
					.append("\" />");
		}
		body.append("</contacts></args>");
		headers.add(new FetionSIPC.HeaderPair("L", StrUtil.getLength(body)));

		FetionSIPC sipc = new FetionSIPC(SIPC_COMMON_HEADER, headers, body
				.toString());
		if (this.SendAndReceiveResponse(sipc)) {
			try {
				if (!sipc.response.getResponseCmdLine().code
						.equals(SIPC_RESPONSE_CODE_OK)) {
					this.onSetText("Get friends' info fail");
					return false;
				} else {
					Document dom = parseXmlDocument(sipc.response.body);
					if (dom != null) {
						NodeList contacts = dom.getDocumentElement()
								.getElementsByTagName("contact");
						this.updateFriendInfo(contacts);
					} else
						return false;
				}
			} catch (Exception e) {
				e.printStackTrace();
				this.onSetText("Get friends' info fail");
				return false;
			}
		} else {
			this.onSetText("Time out while getting friends info.");
			return false;
		}
		return true;
	}

	private void updateFriendInfo(NodeList contacts) {
		for (int i = 0; i < contacts.getLength(); i++) {
			Node statuscode = contacts.item(i).getAttributes().getNamedItem(
					"status-code");
			if (statuscode != null
					&& statuscode.getNodeValue().equals(SIPC_RESPONSE_CODE_OK)) {
				String frienduri = contacts.item(i).getAttributes()
						.getNamedItem("uri").getNodeValue();
				FetionFriend ff = ctx.getFriendManager().getFriend(frienduri);
				if (ff != null) {
					NodeList childs = contacts.item(i).getChildNodes();
					for (int k = 0; k < childs.getLength(); k++) {
						Element n = (Element) childs.item(k);
						if (n.getNodeName().equals("personal")) {
							if (n.getAttributeNode("nickname") != null) {
								ff.setNickName(n.getAttributeNode(
										"nickname").getNodeValue());
							}
							if (n.getAttributeNode("mobile-no") != null) {
								ff.mobile_no = n.getAttributeNode(
										"mobile-no").getNodeValue();
								if (ff.getContactName() == null
										&& FetionService.getService() != null) {
									ff.setContactName(FetionService
											.getService().getContactName(
													ff.mobile_no));
								}
							}
							if (n.getAttributeNode("impresa") != null) {
								ff.impresa = n.getAttributeNode("impresa")
										.getNodeValue();
							}
							this.onFriendInfoChanged(ff);
						}
					}
					ff.setNeedUpdate(false);
				}
			} else if (statuscode != null
					&& statuscode.getNodeValue().equals(
							SIPC_RESPONSE_CODE_NOTEXIST)) {
				String frienduri = contacts.item(i).getAttributes()
						.getNamedItem("uri").getNodeValue();
				if (ctx.getFriendManager().removeFriend(frienduri)) {
					this.onFriendInfoChanged(null);
				}
			}
		}
	}
	
	public void addFriendInfoChangedListener(IFriendInfoChanged obj) {
		this._friendInfoChangedListener.add(obj);
	}

	public void removeFriendInfoChangedListener(IFriendInfoChanged obj) {
		this._friendInfoChangedListener.remove(obj);
	}

	private void onFriendInfoChanged(FetionFriend obj) {
		for (IFriendInfoChanged iic : _friendInfoChangedListener) {
			iic.Happened(obj);
		}
	}
	
	@Override
	public boolean execute() {
		ArrayList<FetionFriend> buddies = ctx.getFriendManager().getBuddies();
		ArrayList<FetionFriend> updateBuddies = new ArrayList<FetionFriend>();
		while (true) {
			updateBuddies.clear();
			for (int i = 0; i < buddies.size(); i++) {
				if (buddies.get(i).isNeedUpdate()) {
					updateBuddies.add(buddies.get(i));
				}
			}
			if (updateBuddies.size() != 0)
				getContactsInfo(updateBuddies);
			else
				break;
		}
		return true;
	}


	@Override
	public boolean received(FetionSIPC sipc) {
		// TODO Auto-generated method stub
		return false;
	}


}